// utils/request.ts
import type { FetchOptions } from 'ofetch';
import store from '@/store';

// 定义 API 响应的基本结构
interface ApiResponse<T = any> {
  code: string;
  data: T;
  msg: string;
  success: boolean;
}

// 定义请求配置选项
interface RequestOptions extends FetchOptions {
  // 是否需要认证
  requireAuth?: boolean;
  // 是否显示错误提示
  showError?: boolean;
  // 自定义错误处理
  errorHandler?: (error: any) => void;
  // 请求超时时间
  timeout?: number;
  // 是否返回完整响应（包含code、msg等）
  returnFullResponse?: boolean;
}
let isCode = false;
// 定义错误类型
class RequestError extends Error {
  code: string;
  data: any;

  constructor(msg: string, code: string, data: any) {
    super(msg);
    this.code = code;
    this.data = data;
    this.name = 'RequestError';
  }
}

// 创建请求实例
class RequestClient {
  private baseURL: string;
  private defaultOptions: RequestOptions;

  constructor(baseURL: string = '/web', defaultOptions: RequestOptions = {}) {
    this.baseURL = baseURL;
    this.defaultOptions = {
      timeout: 10000,
      showError: true,
      requireAuth: false,
      ...defaultOptions,
    };
  }

  // 请求拦截器
  private async requestInterceptor(url: string, options: RequestOptions) {
    const config = { ...this.defaultOptions, ...options };

    // 处理 URL
    const fullUrl = url.startsWith('http') ? url : `${this.baseURL}${url}`;

    // 设置默认 headers
    const headers: Record<string, any> = {
      ...config.headers,
    };

    // 只有在不是 FormData 的情况下才设置 Content-Type
    if (!(config.body instanceof FormData) && !headers['Content-Type']) {
      headers['Content-Type'] = 'application/json';
    }

    // 获取认证 token（避免重复调用）
    const token = getToken();
    if (token) {
      headers.Authorization = `Bearer ${token}`;
      headers.token = token;
    }

    // 添加 clinicId（如果存在）
    const userInfo = getUserInfo();
    if (userInfo?.clinicId) {
      headers.clinicId = userInfo.clinicId;
    }

    return {
      url: fullUrl,
      options: {
        ...config,
        headers,
        // 设置超时
        timeout: config.timeout,
      },
    };
  }

  // 响应拦截器
  private async responseInterceptor<T>(
    response: any,
    options: RequestOptions
  ): Promise<T> {
    // 如果是直接返回的数据（非标准 API 响应格式）
    if (response && typeof response === 'object' && !('code' in response)) {
      return response as T;
    }
    const apiResponse = response as ApiResponse<T>;

    if (apiResponse.code == '402' && !isCode) {
      removeToken();
      isCode = true;
      await navigateTo('/login');
      // 处理未登录状态
      // //console.log('处理未登录状态');
      // ElMessage.error(apiResponse.msg);
      throw new Error('未登录状态，请求终止');
      return new Promise(() => {});
    }
    //console.log(apiResponse.code);

    // 处理业务错误
    if (apiResponse.code !== '200') {
      isCode = false;
      const error = new RequestError(
        apiResponse.msg || '请求失败',
        apiResponse.code,
        apiResponse.data
      );
      if (apiResponse.code == '400') {
        ElMessage({
          message: error.message,
          type: 'error',
          duration: 2000,
        });
      }
      // if (options.errorHandler) {
      //   ElMessage.error(error.message);
      //   options.errorHandler(error);
      // } else if (options.showError) {
      //   // 这里可以集成你的消息提示组件
      //   ElMessage.error(error.message);
      //   //console.error('API Error:', error.message);
      //   // 例如：ElMessage.error(error.message)
      // }

      return options.returnFullResponse
        ? (apiResponse as T)
        : (apiResponse as T);
    }
    // 如果需要完整响应，返回整个 apiResponse，否则只返回 data
    return options.returnFullResponse ? (apiResponse as T) : (apiResponse as T);
  }

  // 通用请求方法
  private async request<T = any>(
    url: string,
    options: RequestOptions = {}
  ): Promise<T> {
    try {
      const { url: fullUrl, options: config } = await this.requestInterceptor(
        url,
        options
      );

      const response = await $fetch(fullUrl, config as any);

      return await this.responseInterceptor<T>(response, options);
    } catch (error: any) {
      // 处理网络错误

      //console.log(error, 'LoginResponse');

      if (error.name === 'RequestError') {
        throw error;
      }

      // 处理其他错误
      const requestError = new RequestError(
        error.msg || '网络请求失败',
        error.status || 500,
        error.data
      );

      if (options.errorHandler) {
        options.errorHandler(requestError);
      } else if (options.showError) {
        //console.error('Network Error:', requestError.message);
      }

      throw requestError;
    }
  }

  // GET 请求
  get<T = any>(url: string, options: RequestOptions = {}): Promise<T> {
    // 过滤params中的空值
    let params = options.params;
    if (params && typeof params === 'object') {
      params = Object.fromEntries(
        Object.entries(params).filter(
          ([, v]) => v !== null && v !== undefined && v !== ''
        )
      );
    }
    return this.request<T>(url, { ...options, params, method: 'GET' });
  }

  // POST 请求
  post<T = any>(
    url: string,
    data?: any,
    options: RequestOptions = {}
  ): Promise<T> {
    let datas: { [key: string]: any } = {};
    for (const key in data) {
      if (Object.prototype.hasOwnProperty.call(data, key)) {
        const element = data[key];
        if (element === null || element === undefined) {
        } else {
          datas[key] = element;
        }
      }
    }
    return this.request<T>(url, { ...options, method: 'POST', body: datas });
  }

  // PUT 请求
  put<T = any>(
    url: string,
    data?: any,
    options: RequestOptions = {}
  ): Promise<T> {
    return this.request<T>(url, { ...options, method: 'PUT', body: data });
  }

  // DELETE 请求
  delete<T = any>(url: string, options: RequestOptions = {}): Promise<T> {
    return this.request<T>(url, { ...options, method: 'DELETE' });
  }

  // PATCH 请求
  patch<T = any>(
    url: string,
    data?: any,
    options: RequestOptions = {}
  ): Promise<T> {
    return this.request<T>(url, { ...options, method: 'PATCH', body: data });
  }

  // 文件上传
  upload<T = any>(
    url: string,
    file: File | FormData,
    options: RequestOptions = {}
  ): Promise<T> {
    const formData = file instanceof FormData ? file : new FormData();
    if (file instanceof File) {
      formData.append('file', file, file.name);
    }

    return this.request<T>(url, {
      ...options,
      method: 'POST',
      body: formData,
    });
  }
}

// 创建默认实例
const request = new RequestClient();

// 创建带认证的实例
const authRequest = new RequestClient('/web', { requireAuth: true });

// 导出实例和类
export { request, authRequest, RequestClient, RequestError };

export type { RequestOptions, ApiResponse };

// 也可以直接导出方法
export const { get, post, put, delete: del, patch, upload } = request;
